importJar("org.slf4j:slf4j-api:jar:1.7.21");
importJar("org.slf4j:slf4j-simple:jar:1.7.21");
importJar('com.jcraft:jsch:jar:0.1.54');
importClass("com.jcraft.jsch.JSch");

importClass("java.util.List");
importClass("java.io.File");
importClass("java.io.BufferedInputStream");
importClass("java.io.FileOutputStream");
importClass("java.io.FileInputStream");

// 私钥.
var sshPrivateKeyPath = System.getProperty("private.key");
if (null == sshPrivateKeyPath) {
    sshPrivateKeyPath = System.getProperty("user.home").replace("\\", "/");
    sshPrivateKeyPath += "/.ssh/id_rsa";
}
console.info("set sshPrivateKeyPath=" + sshPrivateKeyPath);

function SSHClient(host, port) {
    if (null == host || "" === host.trim()) {
        throw "host is empty";
    }
    if (null == port) {
        port = 22;
    }
    this.host = host;
    this.port = port;
    this.timeout = 60000;

    this.login = function (user) {
        this.user = user;
        return this;
    };

    this.login = function (user, password) {
        this.user = user;
        this.password = password;
        return this;
    };

    /**
     * 关闭连接.
     * @param channel channel.
     * @param session session.
     */
    this.close = function (channel, session) {
        try {
            if (channel != null) {
                channel.disconnect();
            }
            if (session != null)
                try {
                    session.disconnect();
                } catch (ignored) {
                }

        } catch (ignored) {
        }
    };

    /**
     * 创建session.
     * @returns {*}
     */
    this.createSession = function () {
        var jsch = new JSch();
        var session = jsch.getSession(this.user, this.host, this.port);
        if (null != this.password) {
            session.setPassword(this.password);
        } else {
            jsch.addIdentity(null, util.readToByteBuffer(sshPrivateKeyPath), null, null);
        }
        var config = new java.util.Properties();
        config.put("StrictHostKeyChecking", "no");
        session.setConfig(config);
        session.connect(this.timeout);
        return session;
    };

    /**
     * 执行命令.
     * @param command
     */
    this.exec = function (command) {
        var session = null;
        var channel = null;
        var inputStream = null;
        try {
            session = this.createSession();
            channel = session.openChannel("exec");
            channel.setCommand(command);
            inputStream = channel.getInputStream();
            channel.connect();
            util.transfer(inputStream,  console.out);
        } catch (e) {
            console.info("exec failed, command=" + command);
            e.printStackTrace(console.err);
        } finally {
            util.closeQuietly(inputStream);
            this.close(channel, session);
        }
    };

    /**
     * 执行命令.
     * @param fromPath
     * @param toPath
     */
    this.download = function (fromPath, toPath) {
        var session = null;
        var channel = null;
        var outputStream = null;
        try {
            session = this.createSession();
            channel = session.openChannel("sftp");
            channel.connect(this.timeout);
            fromPath = fromPath.replace("~", channel.pwd());
            console.info("download start, fromPath=" + fromPath);
            channel.cd(fromPath.substring(0, fromPath.lastIndexOf("/")));
            channel.get(fromPath, new FileOutputStream(new File(toPath)));
            console.info("download success, fromPath=" + fromPath + ", toPath=" + toPath);
        } catch (e) {
            console.info("download failed, fromPath=" + fromPath + ", toPath=" + toPath);
            e.printStackTrace(console.err);
        } finally {
            util.closeQuietly(outputStream);
            this.close(channel, session);
        }
    };

    /**
     * 执行命令.
     * @param fromPath
     * @param toPath
     */
    this.upload = function (fromPath, toPath) {
        var session = null;
        var channel = null;
        var outputStream = null;
        var inputStream = null;
        try {
            session = this.createSession();
            channel = session.openChannel("sftp");
            channel.connect(this.timeout);
            toPath = toPath.replace("~", channel.pwd());
            console.info("upload start, fromPath="+fromPath+", toPath=" + toPath);
            channel.cd(toPath.substring(0, toPath.lastIndexOf("/")));
            if (toPath.endsWith("/")) {
                toPath = fromPath.substring(fromPath.contains("/") ? fromPath.lastIndexOf("/") + 1 : 0);
            } else {
                toPath = toPath.substring(toPath.contains("/") ? toPath.lastIndexOf("/") + 1 : 0);
            }
            var url = util.getFileEveryWhere(fromPath);
            if (null == url) {
                console.error("upload failed, fromPath not exits, fromPath=" + fromPath);
                return;
            }
            inputStream = url.openStream();
            channel.put(inputStream, toPath);
            console.info("upload success, fromPath=" + fromPath + ", toPath=" + toPath);
        } catch (e) {
            console.info("upload failed, fromPath=" + fromPath + ", toPath=" + toPath);
            console.exception(e);
        } finally {
            util.closeQuietly(inputStream);
            util.closeQuietly(outputStream);
            this.close(channel, session);
        }
    };
}
